//
//  GridBluetoothViewController.swift
//  grid-ios-app
//
//  Created by wondertek on 2024/3/26.
//

import UIKit
import CoreBluetooth
import SnapKit

private let Service_UUID: String = "CDD1"
private let Characteristic_UUID: String = "CDD2"

enum GridBluetoothState {
    case  nomalState // 初始状态
    case  stateScanState // 可以开始扫描
    case  scanState // 正在扫描
    case  scanStopState // 停止扫描
    case  linkState // 连接状态
}

class GridBluetoothViewController: GridBaseViewController {
    
    
    //发现的蓝牙外设
    var discoveredPeripheralsArr :[GridBluethoothCellModel] = []
    
    
    lazy var centralManager:CBCentralManager = {
        let c =  CBCentralManager.init()
        return c
    }()
    
    
    // 连接的设备
    private var connectedPeripheral: CBPeripheral?
    
    private var characteristic: CBCharacteristic?
    
    private var bluetoothState: GridBluetoothState = .nomalState {
        didSet {
            print("\(bluetoothState)")
            switch bluetoothState {
            case .nomalState:
                stateBtn.setTitle(NSLocalizedString("扫描设备", tableName: "GridLocalizable", comment: ""), for: .normal)
                break
            case .stateScanState:
                stateBtn.setTitle(NSLocalizedString("扫描设备", tableName: "GridLocalizable", comment: ""), for: .normal)
                break
            case .linkState:
                titleLabel.text = "已连接的设备"
                titleLabel.isHidden = false
                stateBtn.setTitle(NSLocalizedString("断开连接", tableName: "GridLocalizable", comment: ""), for: .normal)
                break
            case .scanState:
                titleLabel.text = "可连接的设备"
                titleLabel.isHidden = false
                stateBtn.setTitle(NSLocalizedString("停止扫描", tableName: "GridLocalizable", comment: ""), for: .normal)
                break
            case .scanStopState:
                titleLabel.text = "可连接的设备"
                titleLabel.isHidden = false
                stateBtn.setTitle(NSLocalizedString("已停止扫描", tableName: "GridLocalizable", comment: ""), for: .normal)
                break
            }
        }
    }
    
    lazy var tableView: UITableView = {
        let tv = UITableView.init(frame: CGRect.zero, style: .grouped)
        tv.backgroundColor = .white
        tv.separatorStyle = .none
        tv.delegate = self
        tv.dataSource = self
        tv.register(GridBluetoothTitleTableViewCell.self, forCellReuseIdentifier: "GridBluetoothTitleTableViewCell")
        view.addSubview(tv)
        return tv
    }()
    
    lazy var stateBtn: UIButton = {
        let button = UIButton(type: .custom)
        button.backgroundColor = .clear
        button.setTitle(NSLocalizedString("扫描设备", tableName: "GridLocalizable", comment: ""), for: .normal)
        button.setTitleColor(UIColor(hex6: 0x404040, alpha: 1.0), for: .normal)
        button.titleLabel!.font = Theme.Font.size(20, bold: true)
        button.addTarget(self, action: #selector(onClickButton), for: .touchUpInside)
        button.backgroundColor  = UIColor(hex6: 0x1E90FF)
        button.layer.masksToBounds = true
        button.layer.cornerRadius = 20
        view.addSubview(button)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        view.backgroundColor = .white
        navigationItem.title = "蓝牙"
        stateBtn.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(30)
            make.right.equalToSuperview().offset(-20)
            make.left.equalToSuperview().offset(20)
            make.height.equalTo(40)
        }
        
        titleLabel.snp.makeConstraints { make in
            make.top.equalTo(stateBtn.snp.bottom).offset(20)
            make.right.equalToSuperview().offset(-20)
            make.left.equalToSuperview().offset(20)
            make.height.equalTo(16)
        }
        
        tableView.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(10)
            make.left.right.bottom.equalToSuperview()
        }
        self.centralManager.delegate = self
    }
    
    
    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor(hex6:0x404040)
        label.font = Theme.Font.size(16)
        label.text = ""
        label.backgroundColor = .clear
        label.textAlignment = .left
        label.isHidden = true
        view.addSubview(label)
        return label
    }()
    
    lazy var bottomView: GridBluetoothBottomView = {
        let view = GridBluetoothBottomView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 200))
        return view
    }()
    
    
    // 开始扫描
    private func startScanForPeripherals() {
        bluetoothState = .scanState
        self.centralManager.scanForPeripherals(withServices: nil, options: nil)
    }
    
    
    ///连接外设
    func connectBluetooth(peripheral: CBPeripheral?) {
        if peripheral != nil {
            self.centralManager.connect(peripheral!, options: nil)
        }
    }
    
    // 断开连接
    func disconnectPeripheral() {
        if let peripheral = connectedPeripheral {
            // 断开连接
            centralManager.cancelPeripheralConnection(peripheral)
        }
    }
    
    // 停止扫描
    func cancelScan() {
        if self.centralManager.isScanning {
            bluetoothState = .scanStopState
            self.centralManager.stopScan()
        }
    }
    
    
    
    // 获取
    private func readValueForCharater(_ sender: Any) {
        self.connectedPeripheral?.readValue(for: self.characteristic!)
    }
    
    // 写入数据
    private func writeMessage(_ message: String?) {
        let data = (message ?? "empty")!.data(using: String.Encoding.utf8)
        self.connectedPeripheral?.writeValue(data!, for: self.characteristic!, type: CBCharacteristicWriteType.withResponse)
    }
    
    @objc func onClickButton() {
        print("onClickButton")
        if bluetoothState == .stateScanState {
            startScanForPeripherals()
        }
        else if bluetoothState == .scanState {
            cancelScan()
        }
        else if bluetoothState == .linkState {
            disconnectPeripheral()
        }
    }
    
    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destination.
     // Pass the selected object to the new view controller.
     }
     */
    
}

extension GridBluetoothViewController: CBCentralManagerDelegate {
    
    // 检测蓝牙是否可用
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("CBCentralManager state:unknown")
            break
        case .resetting:
            print("resetting")
            break
        case .unsupported:
            print("unsupported")
            break
        case .unauthorized:
            print( "unauthorized")
            break
        case .poweredOn:
            print("poweredOn")
            ///扫描设备 -扫描所有设备
            bluetoothState = .stateScanState
            break
        case .poweredOff:
            print("CBCentralManager state:", "poweredOff")
            break
        default:
            print("未知错误")
        }
    }
    
    ///发现设备
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print(peripheral.name ?? "无名称")
        print(peripheral.identifier)
        //过滤存在的蓝牙外设
        var isExisted = false
        for model  in discoveredPeripheralsArr {
            if (model.peripheral.identifier == peripheral.identifier){
                isExisted = true
                break
            }
        }
        if !isExisted {
            var stateLink: GridLinkState  = .noLinking
            if(peripheral.identifier == self.connectedPeripheral?.identifier) {
                stateLink = .isLinking
            }
            let modelP = GridBluethoothCellModel(peripheral: peripheral, state: stateLink)
            discoveredPeripheralsArr.append(modelP)
            tableView.reloadData()
        }
        
    }
    
    ///连接设备成功
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("连接设备成功")
        self.connectedPeripheral = peripheral
        self.bluetoothState = .linkState
        self.tableView.reloadData()
        peripheral.delegate = self
        //开始寻找Services。传入nil是寻找所有Services
        peripheral.discoverServices(nil)
    }
    ///连接设备失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("连接失败:\(error.debugDescription)")
    }
    
    ///断开连接
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        print("断开连接")
        self.connectedPeripheral = nil
        self.bluetoothState = .scanStopState
        self.tableView.reloadData()
        ///// 重新连接
//        central.connect(peripheral, options: nil)
    }
    
}

// 连接蓝牙设备处理
extension GridBluetoothViewController: CBPeripheralDelegate {
    /** 发现服务 */
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let services = peripheral.services {
            for service: CBService in services {
                print("外设中的服务有：\(service)")
                // 这里修改 UDID
                if service.uuid.uuidString == "" {
                    //本例的外设中只有一个服务
                    peripheral.discoverCharacteristics(nil, for: service)
                }
            }
        }
       
       
    }
    
    /** 发现特征 */
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        
        if error != nil{
            // 错误
            print(error?.localizedDescription)
        } else {
            for characteristic: CBCharacteristic in service.characteristics! {
                
                let propertie = characteristic.properties
                
                // 订阅
                if propertie == CBCharacteristicProperties.notify {
                    peripheral.setNotifyValue(true, for: characteristic)
                    
                }
                // 写
                if propertie == CBCharacteristicProperties.write {
                    //char[3]
                    // 这里修改 UDID
                    if characteristic.uuid.uuidString == "" {
                        
                        self.characteristic = characteristic
                        //写入
                        let byte:[UInt8] = [0x3A]
                        let data = Data(bytes: byte, count: 1)
                        
                        for byte in 0..<data.count {
                            print("\(byte)")
                        }
                        self.connectedPeripheral!.writeValue(data, for: self.characteristic!, type: CBCharacteristicWriteType.withResponse)
                        
                    }
                }
                // 读
                if propertie == CBCharacteristicProperties.read {
                    peripheral.readValue(for: characteristic)
                }
            }
        }
    }
    
    /** 订阅状态 */
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        if let error = error {
            print("订阅失败: \(error)")
            return
        }
        if characteristic.isNotifying {
            print("订阅成功")
        } else {
            print("取消订阅")
        }
    }
    
    /** 接收到数据 */
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        let data = characteristic.value
        print(String.init(data: data!, encoding: String.Encoding.utf8) ?? "----")
    }
    
    /** 写入数据 */
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        print("写入数据")
    }
}


extension GridBluetoothViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.bluetoothState == .linkState && self.connectedPeripheral != nil {
            return 1
        }
        return discoveredPeripheralsArr.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "GridBluetoothTitleTableViewCell", for: indexPath) as! GridBluetoothTitleTableViewCell
        if self.bluetoothState == .linkState && self.connectedPeripheral != nil {
            if let per = self.connectedPeripheral {
                let model: GridBluethoothCellModel = GridBluethoothCellModel(peripheral: per, state: .isLinking)
                cell.cellModel = model
            }
        }
        else if indexPath.row >= 0 && indexPath.row < discoveredPeripheralsArr.count {
            let model: GridBluethoothCellModel = discoveredPeripheralsArr[indexPath.row]
            cell.cellModel = model
        }
        cell.delegate = self
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 50
    }
    

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        if self.bluetoothState == .linkState && self.connectedPeripheral != nil {
           return 240
        }
        return 0
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        if self.bluetoothState == .linkState && self.connectedPeripheral != nil {
           return bottomView
        }
        return nil
    }
    
}

extension GridBluetoothViewController: GridBluetoothTitleTableViewCellDelegate {
    func gridBluetoothTitleTableViewCellLink(model: GridBluethoothCellModel?) {
        if (model?.peripheral) != nil {
            self.connectBluetooth(peripheral: model?.peripheral)
        }
    }
   
}

